package br.unifor.cct.mia.evaluate;

import java.io.File;
import java.io.IOException;
import java.util.Map;

import br.unifor.cct.mia.coevolution.InvalidTypeException;
import br.unifor.cct.mia.dataenhancement.Database;
import br.unifor.cct.mia.dataenhancement.GenotypeConverter;
import br.unifor.cct.mia.dataenhancement.Structure;
import br.unifor.cct.mia.evaluate.classification.WekaClassification;
import br.unifor.cct.mia.evolutionary.Genotype;
import br.unifor.cct.mia.evolutionary.Individual;
import br.unifor.cct.mia.evolutionary.SpeciesConstants;
import br.unifor.cct.mia.ga.Ga;

public class WekaHugeScaleFSEvaluate implements Evaluate {

	private Map genesAnt;
	private Structure structure;
	private Database database;
	private Ga ga;
	private String[] options;
	private Integer nBits;
	
	public double cost(Individual gen) {		
		double sum = 0;
		
		Integer hashCode = new Integer(gen.hashCode());
		if (!genesAnt.containsKey(hashCode)) {			

			try {
				GenotypeConverter converter = new GenotypeConverter();
				File f = converter.convert(gen,SpeciesConstants.HUGE_SCALE_FEATURE_SELECTION,"temp/result.txt",structure,database,null,null,nBits);
				
				WekaClassification classificator = new WekaClassification(ga.getLearnerType(),options);
				sum = classificator.evaluate(f);								
			} catch (IOException e1) {
				e1.printStackTrace();
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (InvalidTypeException e) {
				e.printStackTrace();
			}			
			
			genesAnt.put(hashCode, new Double(sum));
		}
		else {
			sum = ((Double)genesAnt.get(hashCode)).doubleValue();
		}
		
		return sum;
	}

	public Object evaluate(Object value,String[] options) {
		this.options = options;               
		Object[] o = (Object[]) value;
		structure = (Structure) o[0];
		genesAnt = (Map) o[1];
		database = (Database) o[2];
		ga = (Ga)o[3];
		nBits = (Integer)o[4]; 
		
		ga.sum = 0;
		ga.indexBestWorst[0] = ga.indexBestWorst[1] = 0;
       
        for(int i = 0; i < ga.configurations.getPopsize(); i++) {   
        	ga.population[i].setFitness(cost((Genotype)ga.population[i]));                    	
            if (ga.population[i].getFitness() > ga.population[ga.indexBestWorst[0]].getFitness()) 
            	ga.indexBestWorst[0] = i;
            else 
            	if (ga.population[i].getFitness() < ga.population[ga.indexBestWorst[1]].getFitness()) 
            		ga.indexBestWorst[1] = i;
            	
            ga.sum += ga.population[i].getFitness();
        }
        
		return ga.population;
	}
}
